/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "message_queue.h"
#include "priority_queue.h"
#include "nfc_log_api.h"
#include "nfc_osi_api.h"
#include <string.h>
#include <inttypes.h>

/**
 * @file message_queue.c
 * @brief 消息队列实现
*/

/**
 * @brief 判断消息队列是否支持多线程
 */
#define IS_MULTITHREAD_MQ(_mq) (_mq->thread_count > 1)
#define THREAD_WAIT_CYCLE 10

static void mq_clean_msg(tQUEUE_ID id, tQUEUE_TAG tag, void* data) {
    (void) id;
    (void) tag;
    if (data == NULL) {
        return;
    }
    tMQ_MSG *msg = (tMQ_MSG*) data;
    mq_free_msg(msg);
}

#if MESSAGE_QUEUE_MAX_THREAD_COUNT > 1
/**
 * @brief 设置消息等待列表
 * @param mq 消息队列指针
 * @param what 需要加入或删除的消息
 * @param add_to_list true表示添加到等待列表，false表示删除
 */
static void set_msg_wait_list(tMESSAGE_QUEUE *mq, uint32_t what, bool add_to_list) {
    if (mq == NULL) {
        return;
    }
    uint8_t i = 0;
    if (add_to_list) {
        // 将what添加到等待列表
        for (i = 0; i < mq->thread_count; i++) {
            if (mq->msg_wait_list[i] < 0 || mq->msg_wait_list[i] == what) {
                // 找到第一个空位置或是what已经存在
                mq->msg_wait_list[i] = what;
                i++; // +1是为了将后续列表中匹配的what置为-1
                break;
            }
        }
    }
    // 将后续列表中匹配的what置为-1
    for (; i < mq->thread_count; i++) {
        if (mq->msg_wait_list[i] == what) {
            mq->msg_wait_list[i] = -1;
        }
    }
}
/**
 * @brief 判断what是否在等待列表中
 * @param mq 消息队列指针
 * @param what 消息
 * @return true表示what在等待列表中，false表示不在
 */
static bool is_msg_in_wait_list(tMESSAGE_QUEUE *mq, uint32_t what) {
    if (mq == NULL) {
        return false;
    }
    for (uint8_t i = 0; i < mq->thread_count; i++) {
        if (mq->msg_wait_list[i] == what) {
            return true;
        }
    }
    return false;
}
#endif

static bool mq_handle_msg(tMESSAGE_QUEUE *mq, tMQ_MSG *msg) {
    if (msg == NULL) {
        return false;
    }
    bool ret = false;
    if (msg->handle == NULL) {
        NFCLOG_W("mq(%s) handle msg: %d, no handler!", mq->name, msg->what);
    } else {
        ret = msg->handle(msg->what, msg->arg1, msg->arg2, msg->args);
        NFCLOG_D("mq(%s) handle msg: %d, ret=%d", mq->name, msg->what, ret);
        if (!ret) {
            // handle函数返回false，表示不需要消息队列释放args，将msg->args置为NULL防止cleanup过程中被释放
            msg->args = NULL;
            NFCLOG_I("mq(%s) handle msg: %d, do not release args", mq->name, msg->what);
        }
    }
#if MESSAGE_QUEUE_MAX_THREAD_COUNT > 1
    if (IS_MULTITHREAD_MQ(mq)) {
        // 只有消息队列开启了多线程支持才需要删除what
        if (osi_mutex_lock(&mq->mutex) == NFC_STATUS_OK) {
            // 将msg->what从等待列表中删除，并通知其他等待线程
            set_msg_wait_list(mq, msg->what, false);
            osi_mutex_notify_all(&mq->mutex);
            osi_mutex_unlock(&mq->mutex);
        } else {
            NFCLOG_E("mq(%s) lock mutex failed", mq->name);
        }
    }
#endif

    mq_free_msg(msg);
    return ret;
}

static tMQ_MSG *get_next_msg(tMESSAGE_QUEUE *mq, bool *exit_task) {
    if (mq == NULL) {
        return NULL;
    }
    if (osi_mutex_lock(&mq->mutex) != NFC_STATUS_OK) {
        return NULL;
    }
    tPRIORITY_QUEUE *queue = &mq->pq;
    // 确保队列非空
    while (mq->state == MQ_STATE_RUNNING && (queue->root == NULL || queue->size == 0)) {
        // 等待新的MSG入队
        osi_mutex_wait_forever(&mq->mutex);
    }
    // 当队列头时间满足时，取出队列头元素
    tMQ_MSG *next_msg = NULL;
    while (mq->state == MQ_STATE_RUNNING || mq->state == MQ_STATE_PREPARE_STOP) {
        tQUEUE_NODE *curr = queue->root;
#if MESSAGE_QUEUE_MAX_THREAD_COUNT > 1
        while (IS_MULTITHREAD_MQ(mq) && curr) {
            // 找到第一个不在等待列表中的消息
            if (is_msg_in_wait_list(mq, ((tMQ_MSG*)curr->data)->what)) {
                // 此时已有同类型消息正在执行，暂时跳过该消息
                NFCLOG_I("mq(%s) msg: %d in wait list, skip this msg for now, arg1=%d", mq->name, ((tMQ_MSG*)curr->data)->what, ((tMQ_MSG*)curr->data)->arg1);
                curr = curr->next;
            } else {
                break;
            }
        }
#endif
        if (curr == NULL || queue->size == 0) {
            // 可能在等待期间队列被清空，或剩余消息都在等待列表中，本次取消息失败
            break;
        }
        tTIMESTAMP curr_time;
        osi_boot_time_ms(&curr_time);
        int64_t time_interval = curr->priority - curr_time;
        if (time_interval <= 0) {
            next_msg = (tMQ_MSG*)pq_remove(queue, curr->id);
            break;
        } else {
            // 等待队列头时间满足要求，或是有新的消息插入
            osi_mutex_wait(&mq->mutex, time_interval);
        }
    }
    if (next_msg == NULL && mq->state > MQ_STATE_RUNNING) {
        // 队列已清空并且队列准备关闭，退出任务
        *exit_task = true;
    }
#if MESSAGE_QUEUE_MAX_THREAD_COUNT > 1
    if (IS_MULTITHREAD_MQ(mq) && next_msg) {
        // 成功获取到消息，在消息执行前将what添加到等待列表，保证同类型消息顺序执行
        set_msg_wait_list(mq, next_msg->what, true);
    }
#endif
    osi_mutex_unlock(&mq->mutex);
    return next_msg;
}

static void *mq_task(void *args) {
    if (args == NULL) {
        NFCLOG_E("mq task args is NULL");
        return NULL;
    }
    tMESSAGE_QUEUE *mq = (tMESSAGE_QUEUE*) args;
    if (osi_mutex_lock(&mq->mutex) != NFC_STATUS_OK) {
        NFCLOG_E("mq(%s) lock mutex failed", mq->name);
        return NULL;
    }
    mq->running_thread_count++;
    osi_mutex_notify_all(&mq->mutex);
    while(mq->state < MQ_STATE_RUNNING) {
        // 暂时释放锁并等待所有工作线程就绪
        osi_mutex_wait_forever(&mq->mutex);
    }
    osi_mutex_unlock(&mq->mutex);
    NFCLOG_I("mq(%s) task running", mq->name);
    while (true) {
        bool exit_task = false;
        tMQ_MSG *msg = get_next_msg(mq, &exit_task);
        if (exit_task) {
            break;
        }
        if (msg != NULL) {
            NFCLOG_D("get msg: %d", msg->what)
            mq_handle_msg(mq, msg);
        }
    }
    NFCLOG_I("mq(%s) exit", mq->name);
    return NULL;
}

/**
 * @brief 初始化消息队列
 *
 * @note 只是初始化队列，不启动任务线程
 * @note 调用此函数前, 请确保mq->state == MQ_STATE_NOT_INIT
 *
 * @param mq 需要初始化的消息队列指针,必须是未初始化过的否则返回失败
 * @param name 消息队列名称, 不可以为NULL
 * @param handle 消息处理函数, 使用mq_alloc_msg分配的消息默认使用此函数处理
 * @param cleanup 消息清理函数, tMQ_MSG中的args字段使用此函数清理
 *
 * @return true 成功, false 失败
 *
*/
bool mq_init(tMESSAGE_QUEUE *mq, tMQ_HANDLE handle, tMQ_CLEANUP cleanup) {
    if (NULL == mq) {
        NFCLOG_E("mq is NULL");
        return false;
    }
    NFCLOG_D("mq->state=%d", mq->state);
    if (mq->state != MQ_STATE_NOT_INIT) {
        NFCLOG_E("mq(%s) init failed", mq->name);
        return false;
    }
    if (osi_mutex_init(&mq->mutex) != NFC_STATUS_OK) {
        NFCLOG_E("mq(%s) init failed", mq->name);
        return false;
    }
    if (!pq_init(&mq->pq, pq_comp_min, mq_clean_msg)) {
        goto cleanup_mutex;
    }
    mq->handle = handle;
    mq->cleanup = cleanup;
    mq->state = MQ_STATE_INIT;
    NFCLOG_D("mq(%s) init success", mq->name);
    return true;
cleanup_mutex:
    osi_mutex_deinit(&mq->mutex);
    NFCLOG_E("mq(%s) init failed", mq->name);
    return false;
}

/**
 * @brief 销毁消息队列
 *
 * 销毁消息队列, 如果队列已经运行，则先停止队列，之后会清空队列
 * 销毁消息队列时，会调用清理函数清理所有消息
 *
 * @param mq 消息队列指针
 *
 * @return 成功返回true, 失败返回false
*/
bool mq_deinit(tMESSAGE_QUEUE *mq) {
    if (mq == NULL) {
        NFCLOG_W("mq is NULL");
        return false;
    }
    if (!mq_stop(mq)) {
        NFCLOG_W("mq(%s) stop failed", mq->name);
    }
    if (osi_mutex_lock(&mq->mutex) != NFC_STATUS_OK) {
        return false;
    }
    NFCLOG_I("mq(%s) deinit", mq->name);
    pq_deinit(&mq->pq, true);
    mq->state = MQ_STATE_NOT_INIT;
    mq->cleanup = NULL;
    mq->handle = NULL;
    osi_mutex_unlock(&mq->mutex);
    osi_mutex_deinit(&mq->mutex);
    return true;
}

static tNFC_STATUS mq_create_thread(tMESSAGE_QUEUE *mq)
{
    tNFC_STATUS ret = NFC_STATUS_OK;
    if (mq->thread_count == 0) {
        // 消息队列至少需要有一个线程
        mq->thread_count = 1;
    }
    if (mq->thread_count > MESSAGE_QUEUE_MAX_THREAD_COUNT) {
        // 线程数量超过最大值, 使用最大值
        mq->thread_count = MESSAGE_QUEUE_MAX_THREAD_COUNT;
    }
    mq->running_thread_count = 0;
    tTHREAD_PARAMS thread_params = {mq_task, mq->name, OS_DEFAULT_THREAD_PRIO, 0, mq, true};
    for (uint8_t i = 0; i < mq->thread_count; i++) {
        ret = osi_thread_create(&mq->thread[i], &thread_params);
        if (ret != NFC_STATUS_OK) {
            NFCLOG_E("mq(%s) thread create failed", mq->name);
            return ret;
        }
    }

    // 等待所有任务线程启动完成
    while (mq->running_thread_count < mq->thread_count) {
        // 任务未全部启动, 继续等待
        ret = osi_mutex_wait(&mq->mutex, THREAD_WAIT_CYCLE);
        if (ret == NFC_STATUS_TIMEOUT) {
            NFCLOG_W("mq(%s) wait mutex timeout, retry", mq->name);
        } else if (ret != NFC_STATUS_OK) {
            NFCLOG_E("mq(%s) wait mutex failed, ret=%d", mq->name, ret);
            return ret;
        }
    }
    return mq->running_thread_count == mq->thread_count ? NFC_STATUS_OK : NFC_STATUS_FAILED;
}

/**
 * @brief 启动消息队列
 *
 * @note 消息队列启动后才可以发送消息
 * @note 只有处于MQ_STATE_INIT状态和MQ_STATE_STOPPED的队列才能启动
 *
 * @param mq 消息队列指针
 *
 * @return 如果启动成功返回true, 失败返回false（如果消息队列已启动或是未初始化也返回false）
 *
*/
bool mq_start(tMESSAGE_QUEUE *mq) {
    if (mq == NULL) {
        return false;
    }
    bool result = false;
    tNFC_STATUS ret = osi_mutex_lock(&mq->mutex);
    if (ret != NFC_STATUS_OK) {
        NFCLOG_E("mq(%s) lock mutex failed, ret=%d", mq->name, ret);
        return false;
    }
    if (mq->state != MQ_STATE_INIT && mq->state != MQ_STATE_STOPPED) {
        NFCLOG_E("mq(%s) start failed, state=%d", mq->name, mq->state);
        osi_mutex_unlock(&mq->mutex);
        return false;
    }
    mq->state = MQ_STATE_STARTING;
    osi_memset_s(&mq->thread, sizeof(tTHREAD) * MESSAGE_QUEUE_MAX_THREAD_COUNT, 0, sizeof(tTHREAD) * MESSAGE_QUEUE_MAX_THREAD_COUNT);
#if MESSAGE_QUEUE_MAX_THREAD_COUNT > 1
    for (uint8_t i = 0; i < MESSAGE_QUEUE_MAX_THREAD_COUNT; i++) {
        mq->msg_wait_list[i] = -1;
    }
#endif

    ret = mq_create_thread(mq);
    if (ret != NFC_STATUS_OK) {
        result = false;
        goto unlock;
    }

    mq->state = MQ_STATE_RUNNING;
    // 通知所有工作线程启动完成
    osi_mutex_notify_all(&mq->mutex);
    NFCLOG_I("mq(%s) start success", mq->name);
    result = true;
unlock:
    osi_mutex_unlock(&mq->mutex);
    if (!result) {
        if (!mq_stop(mq)) {
            NFCLOG_E("mq(%s) stop failed", mq->name);
        }
    }
    return result;
}

/**
 * @brief 等待所有工作线程退出
 */
static bool wait_task_exit(tMESSAGE_QUEUE *mq) {
    if (mq == NULL) {
        return false;
    }
    tNFC_STATUS ret;
    for (uint8_t i = 0; i < mq->thread_count; i++) {
        NFCLOG_I("mq(%s) wait thread(%d) exit", mq->name, i);
        ret = osi_thread_join(mq->thread[i], NULL);
        if (ret != NFC_STATUS_OK) {
            NFCLOG_E("mq(%s) thread(%d) join failed, ret=%d", mq->name, i, ret);
        }
    }
    ret = osi_mutex_lock(&mq->mutex);
    if (ret != NFC_STATUS_OK) {
        NFCLOG_E("mq(%s) lock mutex failed, ret=%d", mq->name, ret);
        return false;
    }
    mq->running_thread_count = 0;
    osi_memset_s(&mq->thread, sizeof(tTHREAD) * MESSAGE_QUEUE_MAX_THREAD_COUNT, 0, sizeof(tTHREAD) * MESSAGE_QUEUE_MAX_THREAD_COUNT);
    mq->state = MQ_STATE_STOPPED;
    osi_mutex_unlock(&mq->mutex);
    return true;
}

/**
 * @brief 停止消息队列
 *
 * 停止消息队列，调用后还未处理的消息将不再处理，之后会清空队列
 * @note 会等待任务线程退出后函数才返回
 *
 * @param mq 消息队列指针
 *
 * @return 成功返回true, 失败返回false
*/
bool mq_stop(tMESSAGE_QUEUE *mq) {
    if (mq == NULL) {
        return false;
    }
    NFCLOG_D("mq(%s) stop+", mq->name);
    bool is_stop = false;
    if (osi_mutex_lock(&mq->mutex) != NFC_STATUS_OK) {
        return false;
    }
    if (mq->state != MQ_STATE_RUNNING && mq->state != MQ_STATE_STARTING) {
        NFCLOG_W("curr mq->state(%d) cannot stop", mq->state);
        osi_mutex_unlock(&mq->mutex);
        return false;
    }
    mq->state = MQ_STATE_STOPPING;
    pq_clear(&mq->pq, true);
    osi_mutex_notify_all(&mq->mutex);
    osi_mutex_unlock(&mq->mutex);

    is_stop = wait_task_exit(mq);

    NFCLOG_D("mq(%s) stop-", mq->name);
    return is_stop;
}

/**
 * @brief 停止消息队列，并且等待消息队列中的所有消息都处理完毕
 *
 * @note 注意，此函数会等待所有消息都处理完毕，如果消息队列中存在大量消息，则等待时间会很长
 * @note 会等待任务线程退出后函数才返回
 *
 * @param mq 消息队列指针
 *
 * @return 成功返回true, 失败返回false
*/
bool mq_wait_stop(tMESSAGE_QUEUE *mq) {
    if (mq == NULL) {
        return false;
    }
    NFCLOG_D("mq(%s)+", mq->name);
    if (osi_mutex_lock(&mq->mutex) != NFC_STATUS_OK) {
        return false;
    }
    if (mq->state != MQ_STATE_RUNNING) {
        NFCLOG_W("curr mq->state(%d)!=MQ_STATE_RUNNING", mq->state);
        osi_mutex_unlock(&mq->mutex);
        return false;
    }
    mq->state = MQ_STATE_PREPARE_STOP;
    osi_mutex_notify_all(&mq->mutex);
    osi_mutex_unlock(&mq->mutex);

    bool is_stop = wait_task_exit(mq);

    NFCLOG_D("mq(%s)-", mq->name);
    return is_stop;
}

/**
 * @brief 分配一个MSG，并使用消息队列的清理函数和处理函数
 *
 * @param mq 消息队列指针
 *
 * @return 成功返回MSG指针，失败返回NULL
*/
tMQ_MSG *mq_alloc_msg(tMESSAGE_QUEUE *mq) {
    if (mq == NULL) {
        return NULL;
    }
    tMQ_MSG *msg = osi_calloc(sizeof(tMQ_MSG));
    if (msg == NULL) {
        return NULL;
    }
    msg->arg1 = 0;
    msg->arg2 = 0;
    msg->args = NULL;
    msg->cleanup = mq->cleanup;
    msg->handle = mq->handle;
    return msg;
}

/**
 * @brief 释放MSG, 并调用其清理函数清理args参数
 *
 * @param msg 消息指针
*/
void mq_free_msg(tMQ_MSG *msg) {
    if (msg == NULL) {
        return;
    }
    NFCLOG_D("msg->what=%d", msg->what);
    if (msg->args != NULL && msg->cleanup != NULL) {
        msg->cleanup(msg->what, msg->arg1, msg->arg2, msg->args);
    }
    osi_free(msg);
}
/**
 * @brief 向消息队列中发送一个立即处理的消息
 *
 * @note 消息队列需要处于运行状态，否则发送失败
 * @note 发送成功后消息队列会管理msg的释放，外部不要再释放msg
 *
 * @param mq 消息队列指针
 * @param msg 消息指针
 *
 * @return 成功返回true, 失败返回false
*/
bool mq_send_msg(tMESSAGE_QUEUE *mq, tMQ_MSG *msg) {
    return mq_send_msg_delay(mq, msg, 0);
}

/**
 * @brief 向消息队列中发送一个延迟处理的消息
 *
 * @note 消息队列需要处于运行状态，否则发送失败
 * @note 发送成功后消息队列会管理msg的释放，外部不要再释放msg
 *
 * @param mq 消息队列指针
 * @param msg 消息指针
 * @param delay_time 延迟时间，单位为毫秒
*/
bool mq_send_msg_delay(tMESSAGE_QUEUE *mq, tMQ_MSG *msg, uint64_t delay_time) {
    if (mq == NULL || msg == NULL) {
        return false;
    }

    if (osi_mutex_lock(&mq->mutex) != NFC_STATUS_OK) {
        return false;
    }

    bool ret = false;

    if (mq->state != MQ_STATE_RUNNING) {
        NFCLOG_W("curr mq->state(%d)!=MQ_STATE_RUNNING", mq->state);
        goto unlock;
    }

    tTIMESTAMP curr_time;
    if (osi_boot_time_ms(&curr_time) != NFC_STATUS_OK) {
        NFCLOG_E("osi_boot_time_ms failed");
        goto unlock;
    }
    uint64_t priority = curr_time + delay_time;

    if (priority < curr_time) {
        // 时间溢出了
        goto unlock;
    }
    NFCLOG_D("what=%d delay=%" PRIu64, msg->what, delay_time);
    ret = pq_enqueue(&mq->pq, msg, priority, (tQUEUE_TAG) msg->what, NULL);
    osi_mutex_notify(&mq->mutex);
unlock:
    osi_mutex_unlock(&mq->mutex);
    return ret;
}

/**
 * @brief 发送一个立即处理的空消息
 *
 * 空消息是指msg的arg参数都未设置只有what的消息，一般是为了触发某些事件
 *
 * @note 消息队列需要处于运行状态，否则发送失败
 * @note 发送成功后消息队列会管理msg的释放，外部不要再释放msg
 *
 * @param mq 消息队列指针
 * @param what 消息类型
 *
 * @return 成功返回true, 失败返回false
*/
bool mq_send_empty_msg(tMESSAGE_QUEUE *mq, uint32_t what) {
    return mq_send_empty_msg_delay(mq, what, 0);
}
/**
 * @brief 发送一个延迟处理的空消息
 *
 * 空消息是指msg的arg参数都未设置只有what的消息，一般是为了触发某些事件
 *
 * @note 消息队列需要处于运行状态，否则发送失败
 * @note 发送成功后消息队列会管理msg的释放，外部不要再释放msg
 *
 * @param mq 消息队列指针
 * @param what 消息类型
 * @param delay_time 延迟时间，单位为毫秒
 *
 * @return 成功返回true, 失败返回false
*/
bool mq_send_empty_msg_delay(tMESSAGE_QUEUE *mq, uint32_t what, uint32_t delay_time) {
    if (mq == NULL) {
        return false;
    }
    tMQ_MSG *msg = mq_alloc_msg(mq);
    if (msg == NULL) {
        return false;
    }
    msg->what = what;
    bool ret = mq_send_msg_delay(mq, msg, delay_time);
    if (!ret) {
        osi_free(msg);
    }
    return ret;
}

/**
 * @brief 发送一个延时处理的带参数的消息
 *
 * @note 消息队列需要处于运行状态，否则发送失败
 *
 * @param mq 消息队列指针
 * @param what 消息类型
 * @param arg1 参数1
 * @param arg2 参数2
 * @param args 指针参数
 * @param delay_time 延迟时间，单位为毫秒
 *
 * @return 成功返回true, 失败返回false
*/
bool mq_send_msg_with_args_delay(tMESSAGE_QUEUE *mq, uint32_t what, uint32_t arg1, uint64_t arg2, void *args, uint32_t delay_time) {
    if (mq == NULL) {
        return false;
    }
    tMQ_MSG *msg = mq_alloc_msg(mq);
    if (msg == NULL) {
        return false;
    }
    msg->what = what;
    msg->arg1 = arg1;
    msg->arg2 = arg2;
    msg->args = args;
    bool ret = mq_send_msg_delay(mq, msg, delay_time);
    if (!ret) {
        osi_free(msg);
    }
    return ret;
}

/**
 * @brief 发送一个立即处理的带参数的消息
 *
 * @note 消息队列需要处于运行状态，否则发送失败
 *
 * @param mq 消息队列指针
 * @param what 消息类型
 * @param arg1 参数1
 * @param arg2 参数2
 * @param args 指针参数
 *
 * @return 成功返回true, 失败返回false
*/
bool mq_send_msg_with_args(tMESSAGE_QUEUE *mq, uint32_t what, uint32_t arg1, uint64_t arg2, void *args) {
    return mq_send_msg_with_args_delay(mq, what, arg1, arg2, args, 0);
}

/**
 * @brief 移除消息队列中指定类型的所有消息
 *
 * @param mq 消息队列指针
 * @param what 消息类型
 *
 * @return 成功返回true, 失败返回false
*/
bool mq_remove_msg(tMESSAGE_QUEUE *mq, uint32_t what) {
    if (mq == NULL) {
        return false;
    }
    if (osi_mutex_lock(&mq->mutex) != NFC_STATUS_OK) {
        return false;
    }
    bool ret = false;
    if (mq->state != MQ_STATE_RUNNING) {
        NFCLOG_W("curr mq->state(%d)!=MQ_STATE_RUNNING", mq->state);
        goto unlock;
    }

    ret = pq_remove_all(&mq->pq, (tQUEUE_TAG) what, true) > 0;
    osi_mutex_notify_all(&mq->mutex);
unlock:
    osi_mutex_unlock(&mq->mutex);
    return ret;
}

/**
 * @brief 清空消息队列
 *
 * @note 必须保证消息队列处于运行状态，否则清空失败
 *
 * @param mq 消息队列指针
 *
 * @return 成功返回true, 失败返回false
*/
bool mq_clear(tMESSAGE_QUEUE *mq) {
    if (mq == NULL) {
        return false;
    }
    if (osi_mutex_lock(&mq->mutex) != NFC_STATUS_OK) {
        return false;
    }
    bool ret = false;
    if (mq->state != MQ_STATE_RUNNING) {
        NFCLOG_W("curr mq->state(%d)!=MQ_STATE_RUNNING", mq->state);
        goto unlock;
    }
    pq_clear(&mq->pq, true);
    NFCLOG_D("pq_clear done");
    osi_mutex_notify_all(&mq->mutex);
    ret = true;
unlock:
    osi_mutex_unlock(&mq->mutex);
    NFCLOG_D("-");
    return ret;
}

